1. Field of the Invention
The present invention relates to the field of input/output (I/O) processing and more particularly to threading models for asynchronous and synchronous I/O.
2. Description of the Related Art
I/O processing refers to the request and receipt of data to and from external devices and logic over I/O ports. Devices coupled to I/O ports can range from communications transceivers to storage devices and the like. I/O ports typically buffer incoming data and pass the incoming data to requesting applications. In this way, applications can access external devices and can incorporate external communications within the application logic itself
I/O process models generally come in two forms: synchronous I/O and asynchronous I/O. In synchronous I/O, a requesting application can post a request for data on an I/O port and can discontinue the logical sequence of the application until the requested data is received on the I/O port. As a practical consequence to synchronous I/O, an application can “hang” while awaiting a response to an I/O request. In contrast to synchronous I/O, in asynchronous I/O, a requesting application can post a request for data on an I/O port and can continue the logical sequence of the application without waiting for a response. Upon receipt of the requested data on the I/O port, the application can retrieve the requested data.
Synchronous I/O often is referred to as “blocking I/O” in that the requesting process remains blocked from continuing execution until a response to the I/O request is received. By comparison, asynchronous I/O often is referred to “non-blocking I/O” in that the requesting process is free to continue processing while awaiting a response to the I/O request. Generally, computing systems either completely support the synchronous I/O model, or the asynchronous I/O model--but not both. For systems that support the asynchronous I/O model, support for the synchronous I/O model must be simulated.
Specifically, since most asynchronous I/O models do not completely support blocking I/O, support for blocking I/O must be simulated by forcing an application thread that requests blocking I/O into a wait. Thereafter, another thread hosting logic enabled to wait on completion events, can wait on the requested I/O until the request is satisfied. Thereafter, the waiter thread can pass the result to the application thread and the application thread can continue execution.
Generally, one of two approaches is taken when working with an asynchronous I/O model. In the former approach, all events are handled by a dedicated thread or threads that either notify a waiting worker thread if the event is for a synchronous I/O request, or that pass the event to a worker thread—generally from a thread pool—to process the event if the event is for an asynchronous I/O request. In the latter approach, events are handled directly on the worker threads as they are received, either notifying a waiting thread, or processing the event.
Both approaches for simulating support for synchronous, blocking I/O in an asynchronous, non-blocking I/O model suffer well-documented deficiencies. In the former approach, when the majority of I/O requests are in the form of non-blocking, asynchronous I/O requests, substantial overhead can be consumed in thread/context switching for every I/O completion event. In the latter approach, when the majority of I/O requests are in the form of blocking, synchronous I/O requests, the worker threads can become quickly overwhelmed making blocking requests, leaving no worker threads to query for events to wake up waiting threads.